package com.lin.linchatgpt.openai.server.imple;

import com.lin.linchatgpt.entity.Message;
import com.lin.linchatgpt.exception.LinException;
import com.lin.linchatgpt.listener.ParsedEventSourceListener;
import com.lin.linchatgpt.service.MessageService;
import com.lin.linchatgpt.service.SubjectService;
import com.lin.linchatgpt.utils.ChatCompletionsUtil;
import com.lin.linchatgpt.utils.ResultCode;
import com.unfbx.chatgpt.OpenAiClient;
import com.unfbx.chatgpt.OpenAiStreamClient;
import com.unfbx.chatgpt.entity.chat.ChatCompletion;
import com.unfbx.chatgpt.utils.TikTokensUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * Copyright(C),2022年-2022,霖霖
 *
 * @author 霖霖
 * @version 1.0
 * @date 2023/6/22 21:32
 * @Description 聊天消息发送机制
 */
@Slf4j
public abstract class BaseSendMessage {
    @Resource
    protected MessageService messageService;
    @Resource
    protected OpenAiStreamClient openAiStreamClient;
    @Resource
    protected SubjectService subjectService;
    @Resource
    protected OpenAiClient openAiClient;
    @Resource
    private ThreadPoolExecutor taskExecutor;


    public ResponseBodyEmitter chatGPTCompletion(List<Message> messages, int type) {
        ResponseBodyEmitter emitter = new ResponseBodyEmitter(3 * 60 * 1000L);

        taskExecutor.execute(()->{

            com.lin.linchatgpt.entity.Message message = messages.get(messages.size() - 1);

            ParsedEventSourceListener parsedEventSourceListener = new ParsedEventSourceListener
                    .Builder()
                    .setMessageService(messageService)
                    .setParentMessageId(message.getId())
                    .setSubjectId(message.getSubjectId())
                    .setEmitter(emitter)
                    .setQuestionMessage(message)
                    .setTaskExecutor(taskExecutor)
                    .setType(type)
                    .build();
            LinkedList<com.unfbx.chatgpt.entity.chat.Message> chatMessage = new LinkedList<>();
            messages.forEach(m -> {
                com.unfbx.chatgpt.entity.chat.Message message1 = new com.unfbx.chatgpt.entity.chat.Message();
                BeanUtils.copyProperties(m, message1);
                chatMessage.add(message1);
            });
            int tokens = TikTokensUtil.tokens(ChatCompletion.Model.GPT_3_5_TURBO.getName(), chatMessage);
            log.info("请求的tokens={}", tokens);
            while (tokens > 3000 && chatMessage.size() > 3) {
                // 删去头两个
                chatMessage.removeFirst();
                chatMessage.removeFirst();
                tokens = TikTokensUtil.tokens(ChatCompletion.Model.GPT_3_5_TURBO.getName(), chatMessage);
            }
            // 若tokens依旧过大，拒绝请求
            if (tokens > 4000)
                throw new LinException(ResultCode.QUESTION_TOO_LONG, "对话过长，请重新建立对话");


//        openAiStreamClient.streamChatCompletion(chatMessage, parsedEventSourceListener);

            openAiStreamClient.streamChatCompletion(ChatCompletionsUtil.getChatCompletion(true, chatMessage, 4096 - tokens)
                    , parsedEventSourceListener);
        });
        return emitter;
    }
}
